package com.dliyun.oap.docs;

import com.dliyun.oap.framework.annotation.ServiceMethodDefinition;
import com.dliyun.oap.framework.annotation.ServiceParamField;
import com.dliyun.oap.framework.exception.OapException;
import com.dliyun.oap.framework.request.AbstractOapRequest;
import com.dliyun.oap.framework.request.OapRequest;
import com.dliyun.oap.framework.request.UploadFile;
import com.dliyun.oap.framework.response.OapResponse;
import com.dliyun.oap.framework.service.RouterService;
import com.dliyun.oap.framework.service.ServiceMethodHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.ClassUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

@Slf4j
@Controller
@RequestMapping("/docs")
public class IndexController {
	@Autowired
	private RouterService routerService;

	@GetMapping("/")
	public String docs() {
		return "redirect:/docs/index.html";
	}

	@ResponseBody
	@GetMapping("/apis")
	public Object apis() {
		Map<String, ServiceMethodHandler> map = this.routerService.getOapContext().getAllServiceMethodHandlers();
		List<ApiMethod> listAllMethods = new ArrayList<>();
		for (ServiceMethodHandler handler : map.values()) {
			ServiceMethodDefinition definition = handler.getServiceMethodDefinition();

			Method method = handler.getHandlerMethod();
			ApiMethod apiMethod = new ApiMethod();
			apiMethod.setMethod(definition.getMethod());
			apiMethod.setTitle(definition.getMethodTitle());
			apiMethod.setHttpAction(definition.getHttpAction());
			apiMethod.setVersion(definition.getVersion());

			List<ApiMethodField> listFields = new ArrayList<>();
			if (method.getParameterTypes().length == 1) {
				Class<?> paramType = method.getParameterTypes()[0];
				Field[] fields = paramType.getDeclaredFields();
				for (Field field : fields) {
					field.setAccessible(true);

					ApiMethodField methodField = new ApiMethodField();
					methodField.setName(field.getName());
					if (ClassUtils.isAssignable(UploadFile.class, field.getType())) {
						methodField.setType("Base64文件");
					} else {
						methodField.setType(field.getType().getSimpleName());
					}
					methodField.setRequired(false);

					Annotation[] annotations = field.getAnnotations();
					if (annotations != null && annotations.length > 0) {
						for (Annotation annotation : annotations) {
							if (ClassUtils.isAssignable(NotNull.class, annotation.annotationType())) {
								methodField.setRequired(true);
							}
							if (ClassUtils.isAssignable(NotBlank.class, annotation.annotationType())) {
								methodField.setRequired(true);
							}
							if (ClassUtils.isAssignable(NotEmpty.class, annotation.annotationType())) {
								methodField.setRequired(true);
							}
							if (ClassUtils.isAssignable(ServiceParamField.class, annotation.annotationType())) {
								ServiceParamField paramField = (ServiceParamField) annotation;
								methodField.setDescribe(paramField.describe());
							}
						}
					}
					listFields.add(methodField);
				}
			}
			apiMethod.setListFields(listFields);
			listAllMethods.add(apiMethod);
		}

		listAllMethods.sort(new Comparator<ApiMethod>() {
			@Override
			public int compare(ApiMethod o1, ApiMethod o2) {
				return o1.getMethod().compareTo(o2.getMethod());
			}
		});
		return listAllMethods;
	}
}
